package com.sunnada.edu.system.pub.securityFilter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.ContextLoader;

import com.sunnada.edu.system.login.dao.LoginDao;
import com.sunnada.edu.system.pub.common.Constants;


public class SecurityFilter implements Filter {
	private Logger log = Logger.getLogger(SecurityFilter.class);

	// 无权限访问时，转向的页面
	private String errorPage;
	// 无会话时转向的页面
	private String noSessionPage;
	
	private String phoneNoSessionPage;

	private AuthoritiesPages authoritiesPages;

	private AutoLoginUrls autoLoginUrls;

	public SecurityFilter() {
	}

	/**
	 * 过滤器初始化
	 */
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	/**
	 * 权限控制过滤器<br>
	 * 根据当前页面url，取得登录者权限，判断有权限的页面，才能进入，无权限页面跳转到错误页面．<br>
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
		long before = System.currentTimeMillis();
		try {

			String url = "";
			HttpSession session = null;
			if (request instanceof HttpServletRequest) {
				// 取得会话
				session = ((HttpServletRequest) request).getSession();
				// 获取请求页面的URL地址
				url = ((HttpServletRequest) request).getServletPath();
				// 过滤无效字符
				url = SqlInjection.transactSQLInjection(url);

				// 判断请求是否是“自动登录”请求，若是，且请求中的用户、密码与配置相符合，则跳转至该请求；否则跳转至登录界面
				// if(autoLoginUrl(url)){
				// String upw = request.getParameter("upw");
				// String autoLoginUser = StringUtils.substring(upw,0, 32);
				// String autoLoginPwd = StringUtils.substring(upw, 32, 64);
				// if(CommConstant.AUTOLOGIN_USER.equals(autoLoginUser) &&
				// CommConstant.AUTOLOGIN_PWD.equals(autoLoginPwd)){
				// filterChain.doFilter(request,response);
				// return ;
				// }
				// }

				// 判断请求是否是“免登录”请求，若是，则跳转至该请求；否则跳转至登录界面
				if (noSessionPage(url)) {
					filterChain.doFilter(request, response);
					return;
				}
			}
			// 用户信息SESSION不存在，跳转至登录界面；否则跳转至请求界面
			String sessionKey = Constants.USER_ID_SESSION;
			String webName=((HttpServletRequest) request).getContextPath();
			if (session == null) {
				if(url.startsWith("/phoneLoginController")){
					//跳回手机端的登入页面
					request.getRequestDispatcher(phoneNoSessionPage).forward(request, response);
				}else if (url.indexOf("loginout")>-1){
					//跳回手机端的登入页面
					request.getRequestDispatcher(noSessionPage).forward(request, response);
				}else{
					//session超时或为空
					printInfo(response, "<script>top.location.href = '"+webName+"/loginController/loginout.shtml';</script>");
				}
			} else if (null != sessionKey && null == session.getAttribute(sessionKey)) {
				if(url.startsWith("/phoneLoginController")){
					//跳回手机端的登入页面
					request.getRequestDispatcher(phoneNoSessionPage).forward(request, response);
				}else if (url.indexOf("loginout")>-1){
					//跳回手机端的登入页面
					request.getRequestDispatcher(noSessionPage).forward(request, response);
				}else{
					//session超时或为空
					printInfo(response, "<script>top.location.href = '"+webName+"/loginController/loginout.shtml';</script>");
				}
			} else {
				// 权限过滤
				if (authUrl(session, url)) {
					filterChain.doFilter(request, response);
					return;
				} else {
					if(url.startsWith("/phoneLoginController")){
						//跳回手机端的登入页面
						request.getRequestDispatcher(phoneNoSessionPage).forward(request, response);
					}else if (url.indexOf("loginout")>-1){
						//跳回手机端的登入页面
						request.getRequestDispatcher(noSessionPage).forward(request, response);
					}else{
						//session超时或为空
						printInfo(response, "<script>top.location.href = '"+webName+"/loginController/loginout.shtml';</script>");
					}
				}
			}

			if (request.getAttribute("javax.servlet.jsp.jspException") != null) {
				Exception ex = (Exception) request.getAttribute("javax.servlet.jsp.jspException");
				if (ex.getCause() != null) {
					String msg = ex.getCause().getMessage();
					if (msg.indexOf("403") != -1) {
						throw new IOException(msg);
					}
				}
			}
			if (log.isDebugEnabled()) {
				log.debug(url + ":" + (before - System.currentTimeMillis()));
			}

		} catch (Exception e) {
			e.printStackTrace();
			request.setAttribute("exception", e);
			request.getRequestDispatcher(errorPage).forward(request, response);
		}
	}
	
	protected void printInfo(ServletResponse response, Object obj) {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = null;
		try {
			out = response.getWriter();
			out.print(obj==null?"":obj);  
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(null != out){
				out.flush();
				out.close();
			}
		}
	}

	private boolean autoLoginUrl(String url) {
		// 自动登录URL
		boolean isAutoLoginUrl = false;
		if (autoLoginUrls.getAutoLoginUrls().get(url) != null) {
			isAutoLoginUrl = true;
		} else {
			isAutoLoginUrl = isMatchUrl(autoLoginUrls.getAutoLoginUrls(), url);
		}
		return isAutoLoginUrl;
	}

	private boolean noSessionPage(String url) {
		// 不需要权限和会话判断的URL
		boolean isNotSessionPages = false;
		if (authoritiesPages.getNotSessionPages().get(url) != null) {
			isNotSessionPages = true;
		} else {
			isNotSessionPages = isMatchUrl(authoritiesPages.getNotSessionPages(), url);
		}
		return isNotSessionPages;
	}

	private boolean isMatchUrl(Map<String, String> urls, String url) {
		boolean isMatch = false;
		for (Iterator<String> i = urls.keySet().iterator(); i.hasNext();) {
			String exp = (String) i.next();
			exp = exp.replaceAll("/", "\\\\/");
			exp = exp.replaceAll("\\.", "\\\\.");
			exp = exp.replaceAll("\\*", ".*");
			Pattern pattern = Pattern.compile(exp, Pattern.CASE_INSENSITIVE);
			Matcher matcher = pattern.matcher(url);
			if (matcher.matches()) {
				isMatch = true;
				break;
			}
		}
		return isMatch;
	}

	private boolean authUrl(HttpSession session, String url) {

		// 1、获取功能权限
		// 2、判断该请求是否属于功能权限
		// 3、该请求属于权限控制，权限为0，跳转错误页面

		List<HashMap<String, String>> userAuth = null;
		if (session.getAttribute(Constants.USER_LINK_PATH) == null) {
			ApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
			HashMap<String, String> param = new HashMap<String, String>();
			// 登录用户ID
			param.put("userId", (String) session.getAttribute(Constants.USER_ID_SESSION));
			LoginDao md = (LoginDao) wac.getBean("loginDaoImpl");
			userAuth = md.getUserFilterMenus(param);
			session.setAttribute(Constants.USER_LINK_PATH, userAuth);
		} else {
			userAuth = (List<HashMap<String, String>>) session.getAttribute(Constants.USER_LINK_PATH);
		}
		boolean f = false;
		if(ALLOW_LINK.get(url) != null){
			f = true;
		}else{
			if (userAuth != null) {
				for (Map<String, String> map : userAuth) {
					String isMenu = map.get("IS_MENU");
					String link = map.get("LINK_PATH");
					if (link != null && !"".equals(link.trim()) && isMenu.equals("1") && link.indexOf("/") > -1) {
						String links[] = link.split("/");
						link = "/" + links[1];
						// link = link.replaceAll("/","\\\\/");
						// link = link.replaceAll("\\.","\\\\.");
						// link = link.replaceAll("\\*",".*");
						// Pattern pattern = Pattern.compile(link,
						// Pattern.CASE_INSENSITIVE);
						// Matcher matcher = pattern.matcher(url);
						if (url.contains(link)) {
							f = true;
							break;
						}
					}
				}
			}
		}
		return f;
	}

	/**
	 * 权限不过滤的路径配置，配置完需重启服务器
	 */
	private static HashMap<String, Boolean> ALLOW_LINK = new HashMap<>();
	static {
		ALLOW_LINK.put("/loginController/home.shtml", true);
		ALLOW_LINK.put("/pageJumpController/*.shtml", true);
		ALLOW_LINK.put("/loginController/getUserMenus.shtml", true);
		ALLOW_LINK.put("/pubController/updatePwdPage.shtml", true);
		ALLOW_LINK.put("/pubController/pwdUpdate.shtml", true);
		ALLOW_LINK.put("/phoneLoginController/home.shtml", true);
		ALLOW_LINK.put("/phoneLoginController/getUserMobileMenus.shtml", true);
	}

	/**
	 * 注销方法
	 */
	public void destroy() {

	}

	/**
	 * 过滤器初始化
	 * 
	 */
	public void doInit() {

	}

	/**
	 * 取得错误页面配置
	 * 
	 * @return 错误页面配置
	 */
	public String getErrorPage() {
		return errorPage;
	}

	/**
	 * 设置错误页面配置 ,由spring 注入
	 * 
	 * @param errorPage
	 *            错误页面配置
	 */
	public void setErrorPage(String errorPage) {
		this.errorPage = errorPage;
	}

	/**
	 * 取得不需安全过滤的页面
	 * 
	 * @return 不需安全过滤的页面
	 */
	public String getNoSessionPage() {
		return noSessionPage;
	}

	/**
	 * 设置不需安全过滤的页面,由spring注入
	 * 
	 * @param noSessionPage
	 *            不需安全过滤的页面
	 */
	public void setNoSessionPage(String noSessionPage) {
		this.noSessionPage = noSessionPage;
	}

	public AuthoritiesPages getAuthoritiesPages() {
		return authoritiesPages;
	}

	public void setAuthoritiesPages(AuthoritiesPages authoritiesPages) {
		this.authoritiesPages = authoritiesPages;
	}

	public AutoLoginUrls getAutoLoginUrls() {
		return autoLoginUrls;
	}

	public void setAutoLoginUrls(AutoLoginUrls autoLoginUrls) {
		this.autoLoginUrls = autoLoginUrls;
	}

	public String getPhoneNoSessionPage() {
		return phoneNoSessionPage;
	}

	public void setPhoneNoSessionPage(String phoneNoSessionPage) {
		this.phoneNoSessionPage = phoneNoSessionPage;
	}

	
}